package edu.del.springbootredisbusinesspractice.service.impl;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import edu.del.springbootredisbusinesspractice.commons.config.RabbitMQConfig;
import edu.del.springbootredisbusinesspractice.commons.exception.OrderException;
import edu.del.springbootredisbusinesspractice.mapper.OrdersMapper;
import edu.del.springbootredisbusinesspractice.pojo.Orders;
import edu.del.springbootredisbusinesspractice.service.OrdersService;
import edu.del.springbootredisbusinesspractice.service.ProductService;
import edu.del.springbootredisbusinesspractice.service.ProductStockService;
import edu.del.springbootredisbusinesspractice.service.repository.ProductStockRepository;
import edu.del.springbootredisbusinesspractice.utils.SnowflakeIdGenerator;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

/**
* @author Del
* @description 订单服务
* @createDate 2025-09-28 09:17:34
 * tryReserve
 * confirm
 * cancel
*/
@Service
@Slf4j
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders>
    implements OrdersService{

    @Autowired
    private OrdersMapper ordersMapper;

    @Autowired
    private ProductService productService;

    @Autowired
    private ProductStockService productStockService;

    @Autowired
    private ProductStockRepository productStockRepository;

    @Autowired
    private SnowflakeIdGenerator snowflakeIdGenerator;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private CacheService cacheService;

    @Transactional
    @Override
    public int placeOrder(int productId, int count) {
        // 1. 先查本地缓存，无/0 则直接拦截
        cacheService.checkStockInLocalCacheOrThrow(productId);

        // 2. 缓存通过，继续走 Redis 扣减等逻辑
        Long stock = productStockRepository.getStockFromRedis(productId);
        // todo：这里选择相信缓存 不做为空值判断，因为可能存在缓存穿透
        // Long newStock = productStockService.decrementStockAndUpdateLocalCache(productId, count);
        Long newStock = productStockService.decrementStockWithLuaScript(productId, count);
        if (newStock == null || newStock < 0) {
            // 恢复本地缓存
            cacheService.updateStockInLocalCache(productId, stock);
            throw new OrderException(1001, "库存不足，无法创建订单");
        }
        // todo：这里也是选择相信缓存 不做为0被减成 -1 判断
        // 2. 构建订单
        Orders order = buildOrder(productId, count);

        // 3. 保存订单
        int insertResult = ordersMapper.insert(order);
        if (insertResult == 0) {
            // 回滚库存
            productStockService.incrementStockAndUpdateLocalCache(productId, count);
            throw new OrderException(1001, "订单创建失败");
        }

        // 4. 发送延迟消息（30分钟后检查是否支付）
        sendOrderDelayMessage(order);

        log.info("【下单成功】订单已创建，等待支付，orderNo: {}", order.getOrderNo());
        return Integer.parseInt(order.getId().toString());
    }

    @Transactional
    @Override
    public boolean paySuccess(String orderNo) {
        Orders order = ordersMapper.selectByOrderNo(orderNo);
        validateOrderForPayment(order);

        order.setStatus(2);
        order.setUpdatedAt(new Date());
        ordersMapper.updateById(order);

        log.info("【支付成功】订单支付完成，orderNo: {}", orderNo);

        // 发送支付成功消息，用于后续处理（发货等）
        sendOrderPaidMessage(order);

        return true;
    }

    @Override
    public Orders getByOrderNo(String orderNo) {
        return ordersMapper.selectByOrderNo(orderNo);
    }

    @Transactional
    @Override
    public boolean cancelOrder(String orderNo) {
        Orders order = ordersMapper.selectByOrderNo(orderNo);
        validateOrderExists(order);

        int oldStatus = order.getStatus();
        order.setStatus(5);
        order.setUpdatedAt(new Date());
        ordersMapper.updateById(order);

        // 如果原来是未支付，则恢复库存
        if (oldStatus == 1) {
            productStockService.incrementStockAndUpdateLocalCache(order.getProductId().intValue(), order.getQuantity());
        }

        // 事务提交后发送取消订单消息
        sendOrderCancelMessageAfterCommit(order);

        log.info("【取消订单】订单已取消，orderNo: {}", orderNo);
        return true;
    }


    // ===== 辅助方法 =====
    private Orders buildOrder(int productId, int count) {
        Orders order = new Orders();
        order.setOrderNo(String.valueOf(snowflakeIdGenerator.nextId()));
        order.setProductId((long) productId);
        order.setUserId(1001L);
        order.setTotalAmount(calculateTotalAmount(productId, count));
        order.setQuantity(count);
        order.setStatus(1); // 未支付
        order.setPaymentMethod("未支付");
        order.setShippingAddress("待填写");
        order.setContactPhone("13800000000");
        order.setContactName("用户");
        order.setCreatedAt(new Date());
        order.setUpdatedAt(new Date());
        return order;
    }

    private BigDecimal calculateTotalAmount(int productId, int count) {
        return productService.getProductById(productId).getPrice().multiply(new BigDecimal(count));
    }

    private void sendOrderDelayMessage(Orders order) {
        rabbitTemplate.convertAndSend(
                RabbitMQConfig.ORDER_EXCHANGE,
                RabbitMQConfig.ORDER_DELAY_ROUTING_KEY,
                order,
                message -> {
                    message.getMessageProperties().setExpiration("15000"); // 30分钟 = 1800000ms
                    return message;
                }
        );
    }

    private void sendOrderPaidMessage(Orders order) {
        rabbitTemplate.convertAndSend(
                RabbitMQConfig.ORDER_EXCHANGE,
                RabbitMQConfig.ORDER_PAID_ROUTING_KEY,
                order
        );
    }

    private void sendOrderCancelMessageAfterCommit(Orders order) {
        // 注册事务同步器，确保消息在事务提交后发出
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                rabbitTemplate.convertAndSend(
                        RabbitMQConfig.ORDER_EXCHANGE,
                        RabbitMQConfig.ORDER_CANCEL_ROUTING_KEY,
                        order
                );
                log.info("【事务提交后】发送取消订单消息，orderNo: {}", order.getOrderNo());
            }
        });
    }

    @Override
    public List<Orders> UnpaidOrderList(Integer id) {
        return ordersMapper.unpaidOrderList(id);
    }




    private void validateOrderForPayment(Orders order) {
        if (order == null) throw new OrderException(1004, "订单不存在");
        if (order.getStatus() != 1) throw new OrderException(1005, "订单状态异常");
    }

    private void validateOrderExists(Orders order) {
        if (order == null) throw new OrderException(1004, "订单不存在");
    }
}




